package com.weilele.mvvm.utils.aria.upload

import androidx.lifecycle.LifecycleOwner
import com.arialyy.aria.core.common.AbsNormalTarget
import com.arialyy.aria.core.config.UploadConfig
import com.arialyy.aria.core.inf.IEntity
import com.arialyy.aria.core.task.UploadTask
import com.arialyy.aria.core.upload.UploadEntity
import com.arialyy.aria.core.upload.UploadTaskListener
import com.arialyy.aria.core.upload.target.HttpBuilderTarget
import com.arialyy.aria.core.upload.target.HttpNormalTarget
import com.weilele.mvvm.base.helper.ILifecycleObserver
import com.weilele.mvvm.utils.aria.AriaHelper
import java.lang.Exception

object MvvmUpload {
    init {
        //保证所以操作调用前Aria 已经初始化完毕
        AriaHelper
    }

    /**
     * downloadTask
     */
    private val uploadTask by lazy { AriaHelper.upload }

    /**
     * 下载参数配置
     */
    fun updateConfig(block: (UploadConfig) -> Unit) {
        block.invoke(AriaHelper.aria.uploadConfig)
    }

    /**
     * 更新task
     */
    fun <Target : AbsNormalTarget<*>> updateTask(
        taskId: Long,
        block: (HttpNormalTarget) -> AbsNormalTarget<Target>
    ) {
        uploadTask
            .load(taskId)
            .let {
                block.invoke(it)
            }
            .save()
    }

    /**
     * 获取所有普通上传任务
     * 获取未完成的普通任务列表{@link #getAllNotCompleteTask()}
     * 获取已经完成的普通任务列表{@link #getAllCompleteTask()}
     */
    val allTask: MutableList<UploadEntity>?
        get() = uploadTask.taskList

    /**
     * 加载HTTP单文件上传任务，用于任务第一次上传，如果需要控制任务停止或删除等操作，请使用{@link #load(long)}
     *
     * @param filePath 文件路径
     */
    fun start(
        url: String,
        filePath: String,
        block: ((build: HttpBuilderTarget) -> Unit)? = null
    ): Long {
        val taskBuild = uploadTask
            .load(filePath)
            .setUploadUrl(url)
        block?.invoke(taskBuild)
        return taskBuild.create()
    }

    /**
     * 继续下载
     */
    fun resume(taskId: Long) {
        uploadTask
            .load(taskId)
            .resume()
    }

    /**
     * 恢复所有下载
     * 有bug，待修复
     */
    fun resumeAllTask() {
        throw IllegalAccessError("上传不支持恢复操作")
    }

    /**
     * 暂停下载
     */
    fun pause(taskId: Long) {
        uploadTask
            .load(taskId)
            .stop()
    }


    /**
     * 暂停所有下载，有bug，待修复
     */
    @Deprecated("有bug，待修复")
    fun pauseAllTask() {
        uploadTask
            .stopAllTask()
    }

    /**
     * 删除任务
     *
     * @param removeFile {@code true} 不仅删除任务数据库记录，还会删除已经完成的文件,总是删除文件
     * {@code false}如果任务已经完成，只删除任务数据库记录
     */
    fun delete(taskId: Long, removeFile: Boolean = false) {
        uploadTask.load(taskId)
            .cancel(removeFile)
    }

    /**
     * 删除所有下载
     */
    fun deleteAllTask(removeFile: Boolean) {
        uploadTask
            .removeAllTask(removeFile)
    }

    /**
     * 判断任务是否存在
     */
    fun taskExists(url: String): Boolean {
        return uploadTask
            .taskExists(url)
    }

    /**
     * 根据id查询下载任务
     */
    fun getDownloadTask(id: Long?): UploadEntity? {
        id ?: return null
        return uploadTask.getUploadEntity(id)
    }

    /**
     * 根据下载地址查询下载任务
     */
    fun getDownloadTask(url: String?): List<UploadEntity>? {
        url ?: return null
        return uploadTask.getUploadEntity(url)
    }

    /**
     * 存在就继续下载
     */
    fun startOrResume(
        url: String,
        filePath: String,
        block: ((build: HttpBuilderTarget) -> Unit)? = null
    ): Long {
        val allDownload = allTask
        var taskId: Long? = null
        allDownload?.let { tasks ->
            tasks.forEach {
                if (it.url == url) {
                    taskId = it.id
                    if (it.state != IEntity.STATE_COMPLETE) {
                        resume(it.id)
                    }
                    return@let
                }
            }
        }
        if (taskId == null) {
            taskId =
                start(url, filePath, block)
        }
        return taskId!!
    }

    /**
     * 添加监听器
     * id：数据库id
     */
    fun addListener(id: Long?, listener: Listener) {
        UploadTaskStatus.listenerMap[id] = listener
    }

    /**
     * 添加监听器
     * lifecycleOwner 生命周期对象，将监听器绑定生命周期
     */
    fun addListener(lifecycleOwner: LifecycleOwner?, listener: LifecycleListener) {
        lifecycleOwner?.lifecycle?.addObserver(listener)
        UploadTaskStatus.listenerMap[listener.id] = listener
    }


    /**
     * 移除监听器
     */
    fun removeListener(id: Long?) {
        UploadTaskStatus.listenerMap.remove(id)
    }

    /**
     * 移除监听器
     */
    fun removeListener(lifecycleOwner: LifecycleOwner?, id: Long?) {
        val listener = getListener(id) ?: return
        if (listener is ILifecycleObserver) {
            lifecycleOwner?.lifecycle?.removeObserver(listener)
        }
        UploadTaskStatus.listenerMap.remove(id)
    }

    /**
     * 移除监听器
     */
    fun removeListener(lifecycleOwner: LifecycleOwner?, listener: LifecycleListener) {
        lifecycleOwner?.lifecycle?.removeObserver(listener)
        UploadTaskStatus.listenerMap.remove(listener.id)
    }

    /**
     * 查询监听器
     */
    fun getListener(id: Long?): Listener? {
        return UploadTaskStatus.listenerMap[id]
    }

    /**
     * 带有生命周期的监听，如果设置了监听，在onStop的时候自动移除，onStart的时候自动监听，防止内存泄漏
     * key：下载时为下载链接地址，上传时为文件地址
     * 如果key发生了变化，请移除此监听，添加新的监听
     */
    open class LifecycleListener(val id: Long) : Listener, ILifecycleObserver {
        private var hasListener = false
        override fun onStart() {
            super.onStart()
            start()
        }

        override fun onStop() {
            super.onStop()
            stop()
        }

        private fun stop() {
            //判断当前时候正在监听
            hasListener = getListener(id) != null
            removeListener(id)
        }

        private fun start() {
            //如果退出的时候添加了监听，则自动添加监听
            if (hasListener) {
                hasListener = false
                addListener(id, this)
            }
        }
    }

    /**
     * 监听器
     */
    interface Listener : UploadTaskListener {

        override fun onWait(task: UploadTask) {

        }

        override fun onPre(task: UploadTask) {
        }

        override fun onTaskPre(task: UploadTask) {
        }

        override fun onTaskResume(task: UploadTask) {
        }

        override fun onTaskStart(task: UploadTask) {
        }

        override fun onTaskStop(task: UploadTask) {
        }

        override fun onTaskCancel(task: UploadTask) {
        }

        override fun onTaskFail(task: UploadTask, e: Exception?) {
        }

        override fun onTaskComplete(task: UploadTask) {
        }

        override fun onTaskRunning(task: UploadTask) {
        }

        override fun onNoSupportBreakPoint(task: UploadTask) {
        }
    }
}